/*
 *
 * Copyright (C) 2007 Texas Instruments Inc
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
/*
 * File name   : saMmapLoopback.c
 * Description : Application used to do NTSC loopback in MMAP memory mode
 */
#include <stdio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/time.h>
//#include <linux/videodev.h>
//#include <linux/videodev2.h>
//#include "golbal_def.h"

#include <linux/videodev.h>
#include <linux/omap_resizer.h>

//#include <linux/omap24xxvout.h>
/*
extern struct overlay_info video_ov;
extern char Esc_Cancle;
extern int video2_close;*/
char Esc_Cancle;


/* structure used to store information of the buffers */

struct buf_info {
	int index;
	unsigned int length;
	char *start;
};

/* Changing the following will result in different number of buffers used */
#define CAPTURE_MAX_BUFFER		3
#define DISPLAY_MAX_BUFFER		3
/* device to be used for capture */
#define CAPTURE_DEVICE		"/dev/video0"
#define CAPTURE_NAME		"Capture"
/* device to be used for display */
#define DISPLAY_DEVICE		"/dev/video1"
#define DISPLAY_NAME		"Display"
/* number of frames to be captured and displayed */
//#define MAXLOOPCOUNT		1000
#define RSZDRIVER	"/dev/omap-resizer"

#if 0
/* absolute path of the sysfs entry for controlling video1 to channel0 */
#define OUTPUTPATH      "/sys/class/display_control/omap_disp_control/video1"
/* absolute path of the sysfs entry for controlling channel0 to LCD */
#define OUTPUTPATH_1      "/sys/class/display_control/omap_disp_control/ch0_output"
#endif
#define WIDTH 720
#define HEIGHT 480
#define LEFT   40
#define TOP     40
#define DEF_PIX_FMT		V4L2_PIX_FMT_UYVY
#define FMT 		RSZ_PIX_FMT_UYVY;
#define RDRV_RESZ_SPEC__MAX_FILTER_COEFF 32



/* capture_buff_info and display_buff_info stores buffer information of capture
   and display respectively. */
static struct buf_info capture_buff_info[CAPTURE_MAX_BUFFER];
static struct buf_info display_buff_info[DISPLAY_MAX_BUFFER];


/* For resizing between */
short gRDRV_reszFilter4TapHighQuality[RDRV_RESZ_SPEC__MAX_FILTER_COEFF]= {
	0, 256, 0, 0, -6, 246, 16, 0, -7, 219, 44, 0, -5, 179, 83, -1, -3,
	130, 132, -3, -1, 83, 179, -5, 0, 44, 219, -7, 0, 16, 246, -6
};
short gRDRV_reszFilter7TapHighQuality[RDRV_RESZ_SPEC__MAX_FILTER_COEFF] = {
	-1, 19, 108, 112, 19, -1, 0, 0, 0, 6, 88, 126, 37, -1, 0, 0,
	0, 0, 61, 134, 61, 0, 0, 0, 0, -1, 37, 126, 88, 6, 0, 0
};



/*===============================initCapture==================================*/
/* This function initializes capture device. It selects an active input
 * and detects the standard on that input. It then allocates buffers in the
 * driver's memory space and mmaps them in the application space.
 */
static int initCapture(int *capture_fd, int *numbuffers, char *inputname,
				char *stdname, struct v4l2_format *fmt)
{
	int ret, i, j;
	struct v4l2_requestbuffers reqbuf;
	struct v4l2_buffer buf;
	struct v4l2_capability capability;
	struct v4l2_input input;
	v4l2_std_id std_id;
	struct v4l2_standard standard;
	int index;

	/* Open the capture device */
	*capture_fd  = open((const char *) CAPTURE_DEVICE, O_RDWR);
	if (*capture_fd  <= 0) {
		printf("Cannot open = %s device\n", CAPTURE_DEVICE);
		return -1;
	}
	printf("\n%s: Opened Channel\n", CAPTURE_NAME);

	/* Get any active input */
	if (ioctl(*capture_fd, VIDIOC_G_INPUT, &index) < 0) {
		perror("VIDIOC_G_INPUT");
		goto ERROR;
	}




	/* Enumerate input to get the name of the input detected */
	memset(&input, 0, sizeof(input));
	input.index = index;
	if (ioctl(*capture_fd, VIDIOC_ENUMINPUT, &input) < 0) {
		perror("VIDIOC_ENUMINPUT");
		goto ERROR;
	}



	printf("%s: Current Input: %s\n", CAPTURE_NAME, input.name);

#if 1
if (ioctl(*capture_fd, VIDIOC_S_INPUT, &index) < 0) {
		perror("VIDIOC_S_INPUT");
		goto ERROR;
	}

	memset(&input, 0, sizeof(input));
	input.index = index;
	if (ioctl(*capture_fd, VIDIOC_ENUMINPUT, &input) < 0) {
		perror("VIDIOC_ENUMINPUT");
		goto ERROR;
	}
	printf("%s: Input changed to: %s\n", CAPTURE_NAME,
						 input.name);
#endif

	/* Store the name of the output as per the input detected */
	strcpy(inputname, (const char *)input.name);

	/* Detect the standard in the input detected */
	if (ioctl(*capture_fd, VIDIOC_QUERYSTD, &std_id) < 0) {
		perror("VIDIOC_QUERYSTD");
		goto ERROR;
	}

	/* Get the standard*/
	if (ioctl(*capture_fd, VIDIOC_G_STD, &std_id) < 0) {
		/* Note when VIDIOC_ENUMSTD always returns EINVAL this
		   is no video device or it falls under the USB exception,
		   and VIDIOC_G_STD returning EINVAL is no error. */
		perror("VIDIOC_G_STD");
		goto ERROR;
	}

	memset(&standard, 0, sizeof(standard));
	standard.index = 0;
	while (1) {
		if (ioctl(*capture_fd, VIDIOC_ENUMSTD, &standard) < 0) {
			perror("VIDIOC_ENUMSTD");
			goto ERROR;
		}

		/* Store the name of the standard */
		if (standard.id & std_id) {
			strcpy(stdname, (const char *)standard.name);
			printf("%s: Current standard: %s\n",
			       CAPTURE_NAME, standard.name);
			break;
		}
		standard.index++;
	}

	/* Check if the device is capable of streaming */
	if (ioctl(*capture_fd, VIDIOC_QUERYCAP, &capability) < 0) {
		perror("VIDIOC_QUERYCAP");
		goto ERROR;
	}
	if (capability.capabilities & V4L2_CAP_STREAMING)
		printf("%s: Capable of streaming\n", CAPTURE_NAME);
	else {
		printf("%s: Not capable of streaming\n", CAPTURE_NAME);
		goto ERROR;
	}

	fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	ret = ioctl(*capture_fd, VIDIOC_G_FMT, fmt);
	if (ret < 0) {
		perror("VIDIOC_G_FMT");
		goto ERROR;
	}


	fmt->fmt.pix.pixelformat = DEF_PIX_FMT;

	ret = ioctl(*capture_fd, VIDIOC_S_FMT, fmt);
	if (ret < 0) {
		perror("VIDIOC_S_FMT");
		goto ERROR;
	}

	ret = ioctl(*capture_fd, VIDIOC_G_FMT, fmt);
	if (ret < 0) {
		perror("VIDIOC_G_FMT");
		goto ERROR;
	}



	if (fmt->fmt.pix.pixelformat != DEF_PIX_FMT) {
		printf("%s: Requested pixel format not supported\n",
		       CAPTURE_NAME);
		goto ERROR;
	}

	/* Buffer allocation
	 * Buffer can be allocated either from capture driver or
	 * user pointer can be used
	 */
	/* Request for MAX_BUFFER input buffers. As far as Physically contiguous
	 * memory is available, driver can allocate as many buffers as
	 * possible. If memory is not available, it returns number of
	 * buffers it has allocated in count member of reqbuf.
	 * HERE count = number of buffer to be allocated.
	 * type = type of device for which buffers are to be allocated.
	 * memory = type of the buffers requested i.e. driver allocated or
	 * user pointer */
	reqbuf.count = *numbuffers;
	reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	reqbuf.memory = V4L2_MEMORY_MMAP;
	ret = ioctl(*capture_fd, VIDIOC_REQBUFS, &reqbuf);
	if (ret < 0) {
		perror("Cannot allocate memory");
		goto ERROR;
	}
	/* Store the number of buffers actually allocated */
	*numbuffers = reqbuf.count;
	printf("%s: Number of requested buffers = %d\n", CAPTURE_NAME,
	       *numbuffers);

	memset(&buf, 0, sizeof(buf));

	/* Mmap the buffers
	 * To access driver allocated buffer in application space, they have
	 * to be mmapped in the application space using mmap system call */
	for (i = 0; i < (*numbuffers); i++) {
		buf.type = reqbuf.type;
		buf.index = i;
		buf.memory = reqbuf.memory;
		ret = ioctl(*capture_fd, VIDIOC_QUERYBUF, &buf);
		if (ret < 0) {
			perror("VIDIOC_QUERYCAP");
			*numbuffers = i;
			goto ERROR1;
		}


		capture_buff_info[i].length = buf.length;
		capture_buff_info[i].index = i;
		capture_buff_info[i].start = mmap(NULL, buf.length,
						PROT_READ |
						PROT_WRITE,
						MAP_SHARED,
						*capture_fd,
						buf.m.offset);

		if (capture_buff_info[i].start == MAP_FAILED) {
			printf("Cannot mmap = %d buffer\n", i);
			*numbuffers = i;
			goto ERROR1;
		}

		memset((void *) capture_buff_info[i].start, 0x80,
			capture_buff_info[i].length);
		/* Enqueue buffers
		 * Before starting streaming, all the buffers needs to be
		 * en-queued in the driver incoming queue. These buffers will
		 * be used by thedrive for storing captured frames. */
		ret = ioctl(*capture_fd, VIDIOC_QBUF, &buf);
		if (ret < 0) {
			perror("VIDIOC_QBUF");
			*numbuffers = i + 1;
			goto ERROR1;
		}
	}

	printf("%s: Init done successfully\n\n", CAPTURE_NAME);
	return 0;

ERROR1:
	for (j = 0; j < *numbuffers; j++)
		munmap(capture_buff_info[j].start,
		       capture_buff_info[j].length);
ERROR:
	close(*capture_fd);
	return -1;
}

/*===============================initDisplay==================================*/
/* This function initializes display device. It sets output and standard for
 * LCD. These output and standard are same as those detected in capture device.
 * It, then, allocates buffers in the driver's memory space and mmaps them in
 * the application space */
static int initDisplay(int *display_fd, int *numbuffers, char *stdname,
				struct v4l2_format *fmt,struct v4l2_format *cap_fmt)
{
	int ret, i, j;
	struct v4l2_requestbuffers reqbuf;
	struct v4l2_buffer buf;
	struct v4l2_capability capability;
	struct v4l2_crop crop;
	//struct v4l2_framebuffer framebuffer;
//	int rotation;
//	char str[200];

	/* Set the video1 pipeline to channel0 overlay */
#if 0
#if 1
	strcpy(str, "echo channel0 > ");
#else
	strcpy(str, "echo channel1 > ");
#endif
	strcat(str, OUTPUTPATH);
	if (system(str)) {
		printf("Cannot set video1 pipeline to TV\n");
		Esc_Cancle=0;
		return 0;
	}
	/* Set the output of channel0 to LCD */
#if 1
	strcpy(str, "echo LCD > ");
	strcat(str, OUTPUTPATH_1);
	if (system(str)) {
		printf("Cannot set output to LCD\n");
		Esc_Cancle=0;
		return 0;
	}
#endif
#endif
	/* Open the video display device */
	*display_fd = open((const char *) DISPLAY_DEVICE, O_RDWR);
	if (*display_fd <= 0) {
		printf("Cannot open = %s device\n", DISPLAY_DEVICE);
		return -1;
	}
	printf("\n%s: Opened Channel\n", DISPLAY_NAME);



	/* Check if the device is capable of streaming */
	if (ioctl(*display_fd, VIDIOC_QUERYCAP, &capability) < 0) {
		perror("VIDIOC_QUERYCAP");
		goto ERROR;
	}

	if (capability.capabilities & V4L2_CAP_STREAMING)
		printf("%s: Capable of streaming\n", DISPLAY_NAME);
	else {
		printf("%s: Not capable of streaming\n", DISPLAY_NAME);
		goto ERROR;
	}

	/* Rotate by 90 degree so that 480x640 resolution will become 640x480 */
#if 0
	rotation = 90;
	ret = ioctl(*display_fd, VIDIOC_S_OMAP2_ROTATION, &rotation);
	if (ret < 0) {
		perror("VIDIOC_S_OMAP2_ROTATION");
		goto ERROR;
	}
#endif

	/* Get the format */
	fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	ret = ioctl(*display_fd, VIDIOC_G_FMT, fmt);
	if (ret < 0) {
		perror("VIDIOC_G_FMT");
		goto ERROR;
	}

	//if (video_ov.resize==1)
		{
		fmt->fmt.pix.width = cap_fmt->fmt.pix.width;
		fmt->fmt.pix.height = cap_fmt->fmt.pix.height;
		}
	/*else
		{
		fmt->fmt.pix.width =  video_ov.ov_width;
		fmt->fmt.pix.height = video_ov.ov_height;
		}
*/
	fmt->fmt.pix.pixelformat = DEF_PIX_FMT;
	ret = ioctl(*display_fd, VIDIOC_S_FMT, fmt);
	if (ret < 0) {
		perror("VIDIOC_S_FMT");
		goto ERROR;
	}

	ret = ioctl(*display_fd, VIDIOC_G_FMT, fmt);
	if (ret < 0) {
		perror("VIDIOC_G_FMT");
		goto ERROR;
	}

	if (fmt->fmt.pix.pixelformat != DEF_PIX_FMT) {
		printf("%s: Requested pixel format not supported\n",
		       CAPTURE_NAME);
		goto ERROR;
	}



#if 0
	ret = ioctl (*display_fd, VIDIOC_G_FBUF, &framebuffer);
	if (ret < 0) {
		perror ("VIDIOC_S_FBUF");
		return 0;

	}

	if(framebuffer.capability & V4L2_FBUF_CAP_LOCAL_ALPHA) {
		framebuffer.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;

		ret = ioctl (*display_fd, VIDIOC_S_FBUF, &framebuffer);
		if (ret < 0) {
			perror ("VIDIOC_S_FBUF");
			return 0;

		}

	}
#endif

#if 1
	crop.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	ret = ioctl(*display_fd, VIDIOC_G_CROP, &crop);
	if (ret < 0) {
		perror("VIDIOC_G_CROP\n");
		goto ERROR;
	}

	/* Set the Cropping parameters */
	crop.c.left = 0;
	crop.c.top = 0;

	//if (video_ov.resize==1)
		{
		crop.c.width =  cap_fmt->fmt.pix.width;;
		crop.c.height =  cap_fmt->fmt.pix.height;
		}
    /*   else
		{
		crop.c.width =  video_ov.ov_width;
		crop.c.height =   video_ov.ov_height;
		}*/

	ret = ioctl(*display_fd, VIDIOC_S_CROP, &crop);
	if (ret < 0) {
		perror("VIDIOC_S_CROP\n");
		goto ERROR;
	}
#endif


#if 1
/* Get the window parameters before setting
	 * and set only required parameters */
	fmt->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
	ret = ioctl(*display_fd, VIDIOC_G_FMT, fmt);
	if (ret < 0) {
		perror("VIDIOC_G_FMT 2\n");
		goto ERROR;
	}
	/* Set the window size */
	/*
	fmt->fmt.win.w.left =video_ov.lo_x;
	fmt->fmt.win.w.top = video_ov.lo_y;
	fmt->fmt.win.w.width = video_ov.ov_width;
	fmt->fmt.win.w.height = video_ov.ov_height;*/
	fmt->fmt.win.w.width = cap_fmt->fmt.pix.width;
	fmt->fmt.win.w.height =  cap_fmt->fmt.pix.height;

	printf("fmt->fmt.win.w.width=%d\n",fmt->fmt.win.w.width);
	printf("fmt->fmt.win.w.height =%d\n",fmt->fmt.win.w.height );

	ret = ioctl(*display_fd, VIDIOC_S_FMT, fmt);
	if (ret < 0) {
		perror("VIDIOC_S_FMT 2\n");
		goto ERROR;
	}


	fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	ret = ioctl(*display_fd, VIDIOC_G_FMT, fmt);
	if (ret < 0) {
		perror("VIDIOC_G_FMT\n");
		goto ERROR;
	}
#endif




	/* Buffer allocation
	 * Buffer can be allocated either from capture driver or
	 * user pointer can be used
	 */
	/* Request for MAX_BUFFER input buffers. As far as Physically contiguous
	 * memory is available, driver can allocate as many buffers as
	 * possible. If memory is not available, it returns number of
	 * buffers it has allocated in count member of reqbuf.
	 * HERE count = number of buffer to be allocated.
	 * type = type of device for which buffers are to be allocated.
	 * memory = type of the buffers requested i.e. driver allocated or
	 * user pointer */
	reqbuf.count = *numbuffers;
	reqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	reqbuf.memory = V4L2_MEMORY_MMAP;
	ret = ioctl(*display_fd, VIDIOC_REQBUFS, &reqbuf);
	if (ret < 0) {
		perror("Cannot allocate memory");
		goto ERROR;
	}
	/* Store the numbfer of buffers allocated */
	*numbuffers = reqbuf.count;
	printf("%s: Number of requested buffers = %d\n", DISPLAY_NAME,
	       (*numbuffers));

	memset(&buf, 0, sizeof(buf));

	/* Mmap the buffers
	 * To access driver allocated buffer in application space, they have
	 * to be mmapped in the application space using mmap system call */
	for (i = 0; i < (*numbuffers); i++) {
		/* Query physical address of the buffers */
		buf.type = reqbuf.type;
		buf.index = i;
		buf.memory = reqbuf.memory;
		ret = ioctl(*display_fd, VIDIOC_QUERYBUF, &buf);
		if (ret < 0) {
			perror("VIDIOC_QUERYCAP");
			(*numbuffers) = i;
			goto ERROR1;
		}

		/* Mmap the buffers in application space */
		display_buff_info[i].length = buf.length;
		display_buff_info[i].index =  i;
		display_buff_info[i].start = mmap(NULL, buf.length,
					     PROT_READ |
					     PROT_WRITE,
					     MAP_SHARED,
					     *display_fd,
					     buf.m.offset);

		if (display_buff_info[i].start == MAP_FAILED) {
			printf("Cannot mmap = %d buffer\n", i);
			(*numbuffers) = i;
			goto ERROR1;
		}
		memset((void *) display_buff_info[i].start, 0x80,
		       display_buff_info[i].length);

		/* Enqueue buffers
		 * Before starting streaming, all the buffers needs to be
		 * en-queued in the driver incoming queue. These buffers will
		 * be used by thedrive for storing captured frames. */
		ret = ioctl(*display_fd, VIDIOC_QBUF, &buf);
		if (ret < 0) {
			perror("VIDIOC_QBUF");
			(*numbuffers) = i + 1;
			goto ERROR1;
		}
	}
	printf("%s: Init done successfully\n\n", DISPLAY_NAME);
	return 0;

ERROR1:
	for (j = 0; j < *numbuffers; j++)
		munmap(display_buff_info[j].start,
			display_buff_info[j].length);
ERROR:
	close(*display_fd);
	return -1;
}

#if 0
static int intResz(int *res_fb,int IN_HSIZE, int IN_VSIZE,int OUT_HSIZE, int OUT_VSIZE)
{
	int ret_val;
	struct rsz_params params;
	int i, read_exp;
	/* Open the resizer driver */
	*res_fb= open(RSZDRIVER, O_RDWR);
	if (*res_fb== -1) {
		perror("Error opening Resizer Driver\n");
		ret_val = -1;
		goto exit3;
	}
	/* Set Parameters */
	params.in_hsize = IN_HSIZE;
	params.in_vsize = IN_VSIZE;
	params.in_pitch = params.in_hsize * 2;
	params.inptyp = RSZ_INTYPE_YCBCR422_16BIT;
	params.vert_starting_pixel = 0;
	params.horz_starting_pixel = 0;
	params.cbilin = 0;
	params.pix_fmt = FMT;
	params.out_hsize = OUT_HSIZE;
	params.out_vsize = OUT_VSIZE;
	params.out_pitch = params.out_hsize * 2;
	params.hstph = 0;
	params.vstph = 0;
	/* As we are downsizing, we put */
	for (i = 0; i < 32; i++)
		params.tap4filt_coeffs[i] =
			gRDRV_reszFilter4TapHighQuality[i];

	for (i = 0; i < 32; i++)
		params.tap7filt_coeffs[i] =
			gRDRV_reszFilter7TapHighQuality[i];

	params.yenh_params.type = 0;
	params.yenh_params.gain = 0;
	params.yenh_params.slop = 0;
	params.yenh_params.core = 0;
	ret_val = ioctl(*res_fb, RSZ_S_PARAM, &params);
	if (ret_val) {
		perror("RSZ_S_PARAM\n");
		goto exit3;
	}
	/*
	printf("IN_HSIZE=%d",IN_HSIZE);
	printf("IN_VSIZE=%d",IN_VSIZE);
	printf("OUT_HSIZE=%d",OUT_HSIZE);
	printf("OUT_VSIZE=%d",OUT_VSIZE);*/
	read_exp = 1;
	ret_val = ioctl(*res_fb, RSZ_S_EXP, &read_exp);
	if (ret_val){
		perror("RSZ_S_EXP\n");
		goto exit3;
	}
	return ret_val;
exit3:
	close(*res_fb);
	return ret_val;
}
#endif

void *camer_threadfun()
{

	int i = 0;
	int ret = 0;
	struct v4l2_format capture_fmt;
	struct v4l2_format display_fmt;
	int capture_fd, display_fd;
	char inputname[15];
	char stdname[15];
	int capture_numbuffers = CAPTURE_MAX_BUFFER, display_numbuffers = DISPLAY_MAX_BUFFER;
	int a;
	struct v4l2_buffer display_buf, capture_buf;
	//struct v4l2_requestbuffers creqbuf;
	struct v4l2_framebuffer framebuffer;

	char *cap_ptr, *dis_ptr;
//	void *in_start, *out_start;
	unsigned int h;

	for(i = 0; i < CAPTURE_MAX_BUFFER; i++) {
		capture_buff_info[i].start = NULL;
	}
	for(i = 0; i < DISPLAY_MAX_BUFFER; i++) {
		display_buff_info[i].start = NULL;
	}
	/* STEP1:
	 * Initialization section
	 * Initialize capture and display devices.
	 * Here one capture channel is opened and input and standard is
	 * detected on that channel.
	 * Display channel is opened with the same standard that is detected at
	 * capture channel.
	 * */
	ret = initCapture(&capture_fd, &capture_numbuffers, inputname,
			stdname, &capture_fmt);
	if(ret < 0) {
		printf("Error in opening capture device for channel 0\n");
		goto ERROR_1;
	}

	/* open display channel */
	ret = initDisplay(&display_fd, &display_numbuffers,
			  stdname, &display_fmt,&capture_fmt);
	if(ret < 0) {
		printf("Error in opening display device\n");
		goto ERROR_1;
	}

#if 0
	ret = intResz(&res_fb,capture_fmt.fmt.pix.width,capture_fmt.fmt.pix.height, video_ov.ov_width,video_ov.ov_height);
	if(ret < 0) {
		printf("Error in opening display device\n");
		goto ERROR_1;
	}

	creqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	creqbuf.memory = V4L2_MEMORY_MMAP;
	creqbuf.count = 2;

	/* Request input buffer */
	ret = ioctl (res_fb, RSZ_REQBUF, &creqbuf);
	if (ret < 0) {
		perror("RSZ_REQBUF\n");
		goto ERROR_1;
	}

	vbuffer.type = creqbuf.type;
	vbuffer.memory = creqbuf.memory;
	vbuffer.index = 0;

	/* This IOCTL just updates buffer */
	ret = ioctl (res_fb, RSZ_QUERYBUF, &vbuffer);
	if (ret < 0) {
		perror("RSZ_QUERYBUF\n");
		printf("Index - %d\n", vbuffer.index);
		goto ERROR_1;
	}

	in_start = mmap(NULL, vbuffer.length, PROT_READ |
			PROT_WRITE, MAP_SHARED, res_fb,
			vbuffer.m.offset);
	if (in_start == MAP_FAILED) {
		perror("mmap error!\n");
		goto ERROR_1;
	}

	vbuffer.index = 1;

	/* This IOCTL just updates buffer */
	ret = ioctl (res_fb, RSZ_QUERYBUF, &vbuffer);
	if (ret) {
		perror("RSZ_QUERYBUF\n");
		printf("Index - %d\n", vbuffer.index);
		goto ERROR_1;
	}

	out_start =
		mmap(NULL, vbuffer.length, PROT_READ |
				PROT_WRITE, MAP_SHARED, res_fb,
				vbuffer.m.offset);
	if (out_start == MAP_FAILED) {
		perror("mmap error!\n");
		goto ERROR_1;
	}
#endif



	/* run section
	 * STEP2:
	 * Here display and capture channels are started for streaming. After
	 * this capture device will start capture frames into enqueued
	 * buffers and display device will start displaying buffers from
	 * the qneueued buffers */

	/* Start Streaming. on display device */
	a = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	ret = ioctl(display_fd, VIDIOC_STREAMON, &a);
	if (ret < 0) {
		perror("VIDIOC_STREAMON");
		goto ERROR;
	}
	printf("%s: Stream on...\n", DISPLAY_NAME);

	/* Start Streaming. on capture device */
	a = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	ret = ioctl(capture_fd, VIDIOC_STREAMON, &a);
	if (ret < 0) {
		perror("VIDIOC_STREAMON");
		goto ERROR;
	}
	printf("%s: Stream on...\n", CAPTURE_NAME);

	/* Set the display buffers for queuing and dqueueing operation */
	display_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	display_buf.index = 0;
	display_buf.memory = V4L2_MEMORY_MMAP;

	/* Set the capture buffers for queuing and dqueueing operation */
	capture_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	capture_buf.index = 0;
	capture_buf.memory = V4L2_MEMORY_MMAP;

	/* One buffer is dequeued from display and capture channels.
	 * Capture buffer will be copied to display buffer.
	 * All two buffers are put back to respective channels.
	 * This sequence is repeated in loop.
	 * After completion of this loop, channels are stopped.
	 */
//	for (i = 0; i < MAXLOOPCOUNT; i++) {
	while(Esc_Cancle ) {


//		printf("Loop %d\n", i);

		/* Dequeue display buffer */
		ret = ioctl(display_fd, VIDIOC_DQBUF, &display_buf);
		if (ret < 0) {
			perror("VIDIOC_DQBUF");
			goto ERROR;
		}

//		printf("1\n");

		/* Dequeue capture buffer */
		ret = ioctl(capture_fd, VIDIOC_DQBUF, &capture_buf);
		if (ret < 0) {
			perror("VIDIOC_DQBUF");
			goto ERROR;
		}

//		printf("2\n");

		cap_ptr =capture_buff_info[capture_buf.index].start;
		dis_ptr=display_buff_info[display_buf.index].start;

#if 0

	memcpy(in_start, cap_ptr, capture_fmt.fmt.pix.width*capture_fmt.fmt.pix.height*2);
	vbuffer.type = creqbuf.type;
	vbuffer.memory = creqbuf.memory;
	vbuffer.index = 0;
	vbuffer.m.userptr = (unsigned int)in_start;

	ret = ioctl(res_fb, RSZ_QUEUEBUF, &vbuffer);
	if (ret < 0) {
		perror("RSZ_QUEUEBUF");
		goto ERROR;
	}
//		printf("1\n");
	vbuffer.index = 1;
	vbuffer.m.userptr = (unsigned int)out_start;

	ret = ioctl(res_fb, RSZ_QUEUEBUF, &vbuffer);
	if (ret < 0) {
		perror("RSZ_QUEUEBUF");
		goto ERROR;
	}
//	printf("2\n");
	ret = ioctl(res_fb, RSZ_RESIZE, NULL);
	if (ret) {
		perror("RSZ_RESIZE\n");
		goto ERROR;
	}

//printf("3\n");
	memcpy(dis_ptr, out_start, display_fmt.fmt.pix.width * display_fmt.fmt.pix.height*2);

#endif

#if 1
		for (h = 0; h < display_fmt.fmt.pix.height; h++) {
			memcpy(dis_ptr, cap_ptr, display_fmt.fmt.pix.width * 2);
			cap_ptr += capture_fmt.fmt.pix.width * 2;
			dis_ptr += display_fmt.fmt.pix.width * 2;
		}
#endif

//		printf("3\n");

		ret = ioctl(capture_fd, VIDIOC_QBUF, &capture_buf);
		if (ret < 0) {
			perror("VIDIOC_QBUF");
			goto ERROR;
		}

//		printf("4\n");

		ret = ioctl(display_fd, VIDIOC_QBUF, &display_buf);
		if (ret < 0) {
			perror("VIDIOC_QBUF");
			goto ERROR;
		}
//		printf("5\n");
	}

	a = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	ret = ioctl(capture_fd, VIDIOC_STREAMOFF, &a);
	if (ret < 0) {
		perror("VIDIOC_STREAMOFF");
		goto ERROR;
	}
	printf("%s: Stream off!!\n", CAPTURE_NAME);

	a = V4L2_BUF_TYPE_VIDEO_OUTPUT;
	ret = ioctl(display_fd, VIDIOC_STREAMOFF, &a);
	if (ret < 0) {
		perror("VIDIOC_STREAMOFF");
		goto ERROR;
	}
	printf("\n%s: Stream off!!\n", DISPLAY_NAME);



	printf("\nLoopback Successful\n\n");



ERROR:


	/* Un-map the buffers */
	for (i = 0; i < display_numbuffers; i++) {
		munmap(display_buff_info[i].start,
		       display_buff_info[i].length);
		display_buff_info[i].start = NULL;
	}
	/* Close the file handle */


	ret = ioctl (display_fd, VIDIOC_G_FBUF, &framebuffer);

	if(framebuffer.capability & V4L2_FBUF_CAP_LOCAL_ALPHA) {
		framebuffer.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA;

		ret = ioctl (display_fd, VIDIOC_S_FBUF, &framebuffer);
	}


	close(display_fd);

	//munmap(out_start, vbuffer.length);
	//munmap(in_start, vbuffer.length);
	//close(res_fb);
ERROR_1:
	/* Un-map the buffers */
	for (i = 0; i < capture_numbuffers; i++) {
		munmap(capture_buff_info[i].start,
		       capture_buff_info[i].length);
		capture_buff_info[i].start = NULL;
	}
	/* Close the file handle */
	Esc_Cancle=0;
	close(capture_fd);



	return 0;
}
